﻿using System;
using System.ComponentModel;
using System.IO;
using System.Runtime.Serialization;
using System.Xml.Serialization;
 
namespace LearningRecords
{
    /// <summary>
    /// 自定义属性下拉效果的类，该类主要继承StringConverter类，并重载该类的一些虚拟方法
    /// </summary>
    public class genderItem : StringConverter
    {
        //true 启用,false 禁用
        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return true;
        }
 
        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            return new StandardValuesCollection(new string[] { "MoveMinPowerDiff", "MoveMaxPowerSum" }); //编辑下拉框中的items
        }
 
		//true：禁用文本编辑，false：启用文本编辑
		public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
        {
            return true;
        }
    }
 

    //[XmlInclude(typeof(DeviceSetting))]
    //[TypeConverter(typeof(ExpandableObjectConverter)), Category("参数")]
    public class DeviceSetting
    {
 
		private int singleScanMode_m;
        
        /// <summary>
		///  单轴扫描模式,0=范围步长方式,1=范围速度方式,2=递增方式
		/// </summary>
		[Browsable(true)]//是否在窗口显示
		[Category("1.扫描参数")]//对参数进行分组
		[DisplayName("单轴扫描模式")]//设置参数显示名称
		[Description("0=范围(步长)\r\n1=范围(速度),2=递增")]//参数描述
		public int SingleScanMode
		{
			get
			{
				return singleScanMode_m;
			}
 
			set
			{
				if (value < 0 || value > 2)//限制设定值，避免错误
				{
					throw new Exception("给定的模式只能是：0,1,2");//抛出异常提示
				}
				singleScanMode_m = value;
			}
		}
 
		#region//常用参数
		/// <summary>
		/// PI耦合扫描范围um
		/// </summary>
		//[ReadOnly(false)]//是否只读
		//[DefaultValue(false)]//默认值
 
		[Browsable(false)]//是否在窗口显示
		[Category("1.参数1")]//对参数进行分组
		[DisplayName("设备名称")]//设置参数显示名称
		[Description("以此保存加载参数")]//参数描述
		public string DevName
		{
			get;
			set;
		}
 
		/// <summary>
		/// 扫描步长um
		/// </summary>
		[Browsable(true)]//是否在窗口显示
        [Category("2.参数2")]//对参数进行分组
        [DisplayName("扫描步长um")]//设置参数显示名称
        [Description("最小步长为0.1um")]//参数描述
        public double ScanStep
        {
            get;
            set;
        }
 
        /// <summary>
        /// Z轴最大绝对位置mm
        /// </summary>
        [Browsable(true)]//是否在窗口显示
        [Category("2.参数2")]//对参数进行分组
        [DisplayName("Z轴最大绝对位置mm")]//设置参数显示名称
        [Description("芯片与耦合头最小间距\r\n安全防呆以免碰撞")]//参数描述
        public double MaxPosZ
        {
            get;
            set;
        }
 
        /// <summary>
        /// 额定参考值
        /// </summary>
        [Browsable(true)]//是否在窗口显示	
        [Category("2.参数2")]//对参数进行分组
        [DisplayName("额定参考值")]//设置参数显示名称
        [Description("判定扫描结果\r\n及自动跟随时是否运动")]//参数描述
        public double RatedRefValue
        {
            get;
            set;
        }
 
        /// <summary>
        /// 多路耦合尾光束额定参考值
        /// </summary>
        [Browsable(true)]//是否在窗口显示	
        [Category("3.参数3")]//对参数进行分组
        [DisplayName("尾光束参考值")]//设置参数显示名称
        [Description("判定多路耦合，\r\n尾光束功率是否达标")]//参数描述
        public double RatedRefValue_End
        {
            get;
            set;
        }
 
        /// <summary>
        /// 扫描范围um
        /// </summary>
        [Browsable(true)]//是否在窗口显示	
        [Category("3.参数3")]//对参数进行分组
        [DisplayName("扫描范围um")]//设置参数显示名称
        [Description("单边最大移动距离\r\n如100um则总长200um")]//参数描述
        public double ScanRange
        {
            get;
            set;
        }
 
        /// <summary>
        /// 单方向扫描一直递减时，最大移动的步长次数--爬山算法扩展
        /// </summary>
        [Browsable(true)]//是否在窗口显示
        [Category("3.参数3")]//对参数进行分组
        [DisplayName("单方向递减次数")]//设置参数显示名称
        [Description("参考值连续递减次数\r\n超过此值则反方向找寻")]//参数描述
        public uint DecrementNum
        {
            get;
            set;
        }
 
		/// <summary>
		/// 角度扫描完后,移动的函数
		/// </summary>
		[Browsable(true)]//是否在窗口显示	
		[Category("4.算法参数")]//对参数进行分组
		[DisplayName("多路-移动函数")]//设置参数显示名称
		[Description("RzRy轴角度扫描完后，\r\n移动到最佳点函数")]//参数描述
		[TypeConverter(typeof(genderItem))] //使用自定义的属性下拉item类3.项目参数
		public string MethodName
		{
			get;
			set;
		}
 
		#endregion
 
		/// <summary>
		/// 
		/// </summary>
		public DeviceSetting()
        {
            RatedRefValue = -0.15;
            RatedRefValue_End = -15;
 
            MaxPosZ = 10;
            ScanStep = 0.001;
            ScanRange = 0.5;
            DecrementNum = 5;
        }
 
        /// <summary>
        /// 
        /// </summary>
        /// <param name="strName">硬件名称</param>
        /// <returns></returns>
        public DeviceSetting(string strName)
        {
            DevName = strName;
        }
 
		/// <summary>
		/// 加载参数
		/// </summary>
		/// <param name="strName">硬件名称</param>
		/// <returns></returns>
		public static DeviceSetting Load(string strName)
		{
			DeviceSetting setting = new DeviceSetting();
			string configFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, strName + "_Config.xml");
 
			if(File.Exists(configFileName))
			{
				FileStream fs = new FileStream(configFileName, FileMode.Open);
				try
				{
					XmlSerializer formatter = new XmlSerializer(typeof(DeviceSetting));
					setting = (DeviceSetting)formatter.Deserialize(fs);
				}
				catch (SerializationException e)
				{
					Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
				}
				finally
				{
					fs.Close();
				}
			}
			
			setting.DevName = strName;
 
			return setting;
		}
		
		/// <summary>
		/// 保存参数
		/// </summary>
		/// <returns></returns>
		public bool Save()
		{
			if (string.IsNullOrEmpty(DevName))
				return false;
 
			bool result = true;
			string configFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DevName + "_Config.xml");
			FileStream fs = new FileStream(configFileName, FileMode.Create);
			XmlSerializer formatter = new XmlSerializer(typeof(DeviceSetting));
			try
			{
				formatter.Serialize(fs, this);
			}
			catch (SerializationException e)
			{
				Console.WriteLine("Failed to serialize. Reason: " + e.Message);
				result = false;
			}
			finally
			{
				fs.Close();
			}
			return result;
		}
	}
}